#ifndef __BLACK_QUATERNION_H__
#define __BLACK_QUATERNION_H__

#include "maths/default.h"
#include "maths/vector.h"

namespace black
{
	// Classes :
	class quat;
	class quat_128;

	// Uses :
	class vec3;
	class angleAxis;
	class mat3x3_128;

	//***************************************************************
	// quat
	//***************************************************************
	class quat
	{
	public:
		bFORCEINLINE			quat();
		bFORCEINLINE			quat( const float x, const float y, const float z, const float w );
		bFORCEINLINE			quat( const quat& q );
		explicit bFORCEINLINE	quat( const float fVals[] );
		bFORCEINLINE			quat( const vec3& vFrom, const vec3& vTo );
		explicit bFORCEINLINE	quat( const angleAxis& aa );
		explicit 				quat( const mat3x3_128& m );

		bFORCEINLINE float			operator []	( const size_t i ) const;
		bFORCEINLINE float&			operator []	( const size_t i );

		bFORCEINLINE quat&			operator += ( const quat& q );
		bFORCEINLINE quat&			operator -= ( const quat& q );
		bFORCEINLINE quat&			operator *= ( const quat& q );
		bFORCEINLINE quat&			operator *= ( const float f );
		bFORCEINLINE quat&			operator /= ( const float f );

		bFORCEINLINE quat			operator* ( const quat& q ) const;
		bFORCEINLINE quat			operator* ( const float f ) const;
		bFORCEINLINE quat			operator/ ( const float f ) const;
		bFORCEINLINE quat			operator+ ( const quat& q ) const;
		bFORCEINLINE quat			operator- ( const quat& q ) const;

		bFORCEINLINE void			conjugate		();
		bFORCEINLINE float			length			() const;
		bFORCEINLINE float			squaredLength	() const;
		bINLINE void				setMult			( const quat& q1, const quat& q2 );
		bFORCEINLINE float			dot				( const quat& q ) const;
		bFORCEINLINE vec3			rot				( const vec3& v ) const;
		bFORCEINLINE vec3			invRot			( const vec3& v ) const;
		bFORCEINLINE quat&			normalize		();
		bFORCEINLINE bool			isUnit			() const;
		bFORCEINLINE quat&			nlerp			( const quat& q1, const quat& q2, float t );
		quat&						slerp			( const quat& q1, const quat& q2, float t );

		bFORCEINLINE bool			isValid			() const;

		static const quat ZERO;

		float x, y, z, w;
	};

	//***************************************************************
	// quat_128
	//***************************************************************
	class bALIGN16 quat_128 : public quat
	{
	public:
		bFORCEINLINE			quat_128();
		bFORCEINLINE			quat_128( const float x, const  float y, const float z, const float w );
		bFORCEINLINE			quat_128( const quat& q );
		bFORCEINLINE			quat_128( const quat_128& q );
		explicit bFORCEINLINE	quat_128( const float fVals[] );

		bFORCEINLINE operator __m128&();
		bFORCEINLINE operator const __m128&() const;

		static const quat_128 ZERO;
	};
}

#include "maths/inl/quaternion.inl"

#endif // __BLACK_QUATERNION_H__
//---------------------------------------------------------------------------------------
// Copyright (c) 2009 Jounayd Id Salah.
// All rights reserved.
//---------------------------------------------------------------------------------------
